package com.lt.flashcard.auth;

/**
 * Provide Realm to work with Apache Shiro. This provide authentication and authorization again Mongo DB
 * @author Thanh Thong - Lactien JSC
 */

import java.util.HashSet;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import com.lt.flashcard.model.entity.Permission;
import com.lt.flashcard.model.entity.Role;
import com.lt.flashcard.model.entity.User;
import com.lt.flashcard.model.service.AAService;
import com.lt.flashcard.model.service.Repository;
import com.lt.flashcard.model.service.UserService;

public class MongoRealm extends AuthorizingRealm {

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

        if (principals == null) {
            throw new AuthorizationException("PrincipalCollection method argument cannot be null.");
        }

        UserService us = Repository.getInstance().getUserService();
        String username = (String) getAvailablePrincipal(principals);
        User user = us.findByUsername(username);
        if (user == null) {
            throw new AuthorizationException("Unknow user");
        }

        Set<String> rolesName = new HashSet<String>();
        for (Role role : user.getRoles()) {
            rolesName.add(role.getName());
        }

        Set<String> permName = new HashSet<String>();
        for (Permission perm : user.getPermissions()) {
            permName.add(perm.getName());
        }

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(rolesName);
        info.setStringPermissions(permName);

        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        String username = upToken.getUsername();

        if (StringUtils.isBlank(username)) {
            throw new AuthenticationException("Username can't be null");
        } else {
            UserService us = Repository.getInstance().getUserService();
            User user = us.findByUsername(username);
            if (user == null) {
                throw new UnknownAccountException("Can't find user [" + username + "]");
            } else {
                String np = user.getPassword();
                if (user.getLogin() == null) {
                    AAService asrv = Repository.getInstance().getAAService();
                    np = asrv.hashPassword(np);
                }
                return new SimpleAuthenticationInfo(user.getUsername(), np.toCharArray(), getName());
            }
        }
    }
}
